package com.clp.protocol.iec104.iec104.client.state;

import com.clp.protocol.iec104.iec104.apdu.Apdu;
import com.clp.protocol.iec104.iec104.apdu.IApdu;
import com.clp.protocol.iec104.iec104.client.async.MasterPromise;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 主站接收子站初始化结束状态
 */
@Slf4j
public class RecvInitEndMasterState extends AbstractMasterState {

    private enum State {
        NOT_RECV_INIT_END,
        RECV_INIT_END
    }

    private volatile State state;

    private volatile Date lastNotRecvInitEndTime;

    public RecvInitEndMasterState(InMasterStateManager stateManager) {
        super(stateManager);
        resetState();
    }

    @Override
    protected Future<Void> resetState() {
        Promise<Void> promise = createPromise(Void.class);
        this.state = State.NOT_RECV_INIT_END;
        this.lastNotRecvInitEndTime = new Date();
        return promise.setSuccess(null);
    }

    @Override
    protected Future<Void> refreshState() {
        return resetState();
    }

    @Override
    public Apdu updateStateBySending(Apdu apdu) {
        return apdu;
    }

    @Override
    public Apdu updateStateByRecving(Apdu apdu) {
        if (apdu == null || !apdu.isIType()) return apdu;
        IApdu iApdu = apdu.castToIType();
        switch (iApdu.getIAsdu().getTypeTag()) {
            case M_EI_NA_1: // 初始化结束
                switch (iApdu.getIAsdu().getCot().getCause()) {
                    case COT_INIT: // 初始化
                        if (state == State.NOT_RECV_INIT_END) {
                            state = State.RECV_INIT_END;
                        }
                        log.info("子站初始化结束，第一次发送总召唤100和总召唤101（电度量召唤");
                        getStateManager().getInMaster().getApduSender().sendIApduOfTotalCall100();
                        getStateManager().getInMaster().getApduSender().sendIApduOfTotalCall101();
                        break;
                }
                break;
        }
        return iApdu;
    }

    @Override
    protected ScheduledTask getScheduledTask() {
        return new ScheduledTask(0, 1, TimeUnit.SECONDS) {
            @Override
            public void run() {
                if (!getStateManager().getInMaster().stateInfo().isStartedDt()) {
                    lastNotRecvInitEndTime = new Date();
                    return;
                }

                switch (state) {
                    case NOT_RECV_INIT_END:
                        // TODO 暂时如此
                        if (new Date().getTime() - lastNotRecvInitEndTime.getTime() > 3 * 1000) {
                            log.warn("启动传输后3秒内没有收到初始化结束报文，手动设置初始化结束");
                            state = State.RECV_INIT_END;
                            getStateManager().getInMaster().getApduSender().sendIApduOfTotalCall100();
                            getStateManager().getInMaster().getApduSender().sendIApduOfTotalCall101();
                        }
                        break;
                    case RECV_INIT_END:
                        // 收到初始化结束后无异常处理
                        break;
                }
            }
        };
    }

    @Override
    public <V> MasterPromise<V> register(MasterPromise<V> sendPromise) {
        return sendPromise;
    }

    public boolean isRecvedInitEnd() {
        return state == State.RECV_INIT_END;
    }
}
